#include "gazell_params_cfg.h"

// #if (ROLE == DEVICE) 
#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#include "gzll.h"
#include "gzp.h"

//-----------------------------------------------------------------------------
// Internal (static) function prototypes
//-----------------------------------------------------------------------------
static bool gzp_tx_packet(const uint8_t* tx_packet, uint8_t length, uint8_t pipe);

// ==================================================================
/// @brief  : 设备配网前必须调用
// ==================================================================
void gzp_init(void)
{
    // 恢复默认跳频表
    uint8_t chan[] = GZLL_DEFAULT_CHANNEL_TAB;
    gzll_set_channels(chan, GZLL_DEFAULT_CHANNEL_TAB_SIZE);
}

// ==================================================================
/// @brief  : 设备请求系统通讯地址
/// @param  : gzp_system_address 设备获取到主机的地址，长度固定为5个字节
/// @returns: true 收到主机发的系统地址
/// @returns: false 没有收到主机发的系统地址
// ==================================================================
bool gzp_address_req_send(uint8_t *gzp_system_address)
{
    uint8_t i;
    bool retval = false;
    uint8_t address_req[GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH];
    uint8_t rx_payload[GZLL_MAX_PAYLOAD_LENGTH];
    uint16_t temp_power, temp_tx_timeout, temp_device_mode;

    if (gzll_get_state() == GZLL_IDLE) {
        // Store parameters that are temporarily changed
        temp_tx_timeout = gzll_get_param(GZLL_PARAM_TX_TIMEOUT);
        temp_power = gzll_get_param(GZLL_PARAM_OUTPUT_POWER);
        temp_device_mode = gzll_get_param(GZLL_PARAM_DEVICE_MODE);

        // Modify parameters
        gzll_set_param(GZLL_PARAM_TX_TIMEOUT, GZP_REQ_TX_TIMEOUT);
        gzll_set_param(GZLL_PARAM_OUTPUT_POWER, GZP_POWER);
        gzll_set_param(GZLL_PARAM_DEVICE_MODE, 0);

        // Flush RX FIFO
        gzll_rx_fifo_flush();

        // Build "request" packet
        address_req[0] = GZP_CMD_HOST_ADDRESS_REQ;

        // Send a number of packets in order to broadcast that devices not within
        // close proximity must back off.
        for (i = 0; i < GZP_MAX_BACKOFF_PACKETS; i++) {
            if (!gzp_tx_packet(address_req, GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, 0)) {
                break;
            }
        }

        port_delay_rx_periods(GZP_TX_ACK_WAIT_TIMEOUT);

        // Send message for fetching pairing response from host.
        address_req[0] = GZP_CMD_HOST_ADDRESS_FETCH;

        if (gzp_tx_packet(&address_req[0], GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, 0)) {
            // If pairing response received
            if (gzll_rx_fifo_read(rx_payload, NULL, NULL)) {
                if (rx_payload[0] == GZP_CMD_HOST_ADDRESS_RESP) {
                    memcpy(gzp_system_address, &rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH);
                    gzp_update_radio_params(&rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS]); 
                    retval = true;
                }
            }
        } else {
            port_delay_rx_periods(GZP_NOT_PROXIMITY_BACKOFF_RX_TIMEOUT - GZP_TX_ACK_WAIT_TIMEOUT);
        }

        port_delay_rx_periods(GZP_STEP1_RX_TIMEOUT);

        // Clean-up and restore parameters temporarily  modified
        gzll_rx_fifo_flush();
        gzll_tx_fifo_flush();
        gzll_set_param(GZLL_PARAM_TX_TIMEOUT, temp_tx_timeout);
        gzll_set_param(GZLL_PARAM_OUTPUT_POWER, temp_power);
        gzll_set_param(GZLL_PARAM_DEVICE_MODE, temp_device_mode);
    }
    return retval;
}

// ==================================================================
/// @brief  : 发送数据包
/// @param  : tx_packet 需要发送的数据包
/// @param  : length 数据包长度
/// @param  : pipe 指定发送数据的通道
/// @returns: true or false 发送成功或失败
// ==================================================================
static bool gzp_tx_packet(const uint8_t* tx_packet, uint8_t length, uint8_t pipe)
{
    if (gzll_tx_data(tx_packet, length, pipe)) {
        while (gzll_get_state() != GZLL_IDLE) {
            port_feed_wdt();
        }
        return gzll_tx_success();
    }
    return false;
}


// #endif
